#!/usr/bin/env python
import DDI_Crawler

config_api_num = 'not_init'
config_url = 'not_init'
config_sub_handle = 'not_init'
config_first_func = 'not_init'
config_last_func = 'not_init'

########### Change only the next line for different config ############
config_template = "DDI9"
######################################################################

if (config_template == "DDI9"):
    config_api_num      = '9'
    config_url          = 'http://msdn.microsoft.com/en-us/library/ff544519%28v=VS.85%29.aspx'
    config_sub_handle   = ' '
    config_first_func   = 'SetRenderState'
    config_last_func    = 'ResolveSharedResource'
    #config_last_func   = 'SetTextureStageState' #for debug
elif (config_template == "DDI10"):
    config_api_num      = '10'
    config_url          = 'http://msdn.microsoft.com/en-us/library/ff541833'
    config_sub_handle   = '.pDrvPrivate'
    config_first_func   = 'DefaultConstantBufferUpdateSubresourceUP'
    config_last_func    = 'SetTextFilterSize'
    #config_last_func   = 'PsSetShader' #for debug
elif (config_template == "DDI10_1"):
    config_api_num      = '10_1'
    config_url          = 'http://msdn.microsoft.com/en-us/library/ff541873'
    config_sub_handle   = '.pDrvPrivate'
    config_first_func   = 'DefaultConstantBufferUpdateSubresourceUP'
    config_last_func    = 'ResourceCopyRegion'
    #config_last_func   = 'PsSetShader' #for debug
elif (config_template == "DDI11"):
    config_api_num      = '11'
    config_url          = 'http://msdn.microsoft.com/en-us/library/ff542141%28v=VS.85%29.aspx'
    config_sub_handle   = '.pDrvPrivate'
    config_first_func   = 'DefaultConstantBufferUpdateSubresourceUP'
    config_last_func    = 'CopyStructureCount'
    #config_last_func   = 'PsSetShader' #for debug 

func_sigs = DDI_Crawler.GetFunctionSignatures(config_url,config_first_func, config_last_func)

print "%d DDI %s functions found." % (len(func_sigs),config_api_num)

#static VOID APIENTRY VsSetConstantBuffers(D3D10DDI_HDEVICE hDevice,UINT StartBuffer,UINT NumBuffers,const D3D10DDI_HRESOURCE *phBuffers)


RET_VAL_NOT_FOUND = 0xFFFFFF 


def SafeFind(str,sub_str):
    ind = str.find(sub_str)
    if ind == -1:
        return RET_VAL_NOT_FOUND
    return ind

def FindRetVal_Void(str):
    o = SafeFind(str,"VOID")
    return o

def FindRetVal_Other(str):
    o1 = SafeFind(str,"HRESULT")
    o2 = SafeFind(str,"bool")
    o3 = SafeFind(str,"BOOL")
    o4 = SafeFind(str,"SIZE_T")
    return min(o1,o2,o3,o4)

def FindRetVal(str):
    o1 = FindRetVal_Void(str)
    o2 = FindRetVal_Other(str)
    return min(o1,o2)
    
def FindLastClosingSograim(func):
    pos = 0
    found_pos = 0
    for c in func:
        if c == ")":
            found_pos = pos
        pos +=1
    return found_pos      

def ExtractArgumentsList(func):    
    args_list = []  
   
    last_sograim_pos = FindLastClosingSograim(func)
    str_list = list(func)
    str_list[last_sograim_pos] = ','
    func_help = "".join(str_list)
    
    next_search_start_pos = 0
    while (True):
        next_search_start_pos = func_help.find(",",next_search_start_pos+1)
        
        if (next_search_start_pos == -1):
            break
        #extract parameter name
        char_pos = next_search_start_pos
        char = 0
        while (char!=' ' and char!='*'):
            char = func[char_pos]
            char_pos-=1
        par = func[char_pos+2:next_search_start_pos]
        #print par
        args_list.append(par.replace('\n',' '))
    return args_list


print "Header Section:"
print "***************"


for sig in func_sigs:
#    if 'CalcPrivateShaderSize' in sig:
#        print "found"
    ind = FindRetVal(sig)
    func = sig[ind:]
    print "static %s;" % func

    
print "Passthrough Implementation:"
print "***************************"
    
class_name = 'DeviceFuncs%s' % config_api_num  
    
    
  
    
    
for sig in func_sigs:
    
    ind = FindRetVal(sig)
    func = sig[ind:]
    
    
    # "inject" class scopre name
    apientry_pos = func.find('APIENTRY')
    func_with_class_scope = func[:apientry_pos+len('APIENTRY')+1] + class_name + "::" + func[apientry_pos+len('APIENTRY')+1:]
    print func_with_class_scope
    
    func_name = func[func.find('APIENTRY')+len('APIENTRY')+1:func.find("(")]
    
    # print function body    
    print "{"
    print "\tDevice%s *pDevice = OpenAdapter%s::getDeviceByHandle(hDevice%s);" % (config_api_num,config_api_num,config_sub_handle)
    ret_str = ""
    if FindRetVal_Void(sig) == RET_VAL_NOT_FOUND:
        ret_str = "return "
    print "\t%spDevice->getFuncs%s().getDt(OpenAdapter::renderingGPU()).pfn%s(" % (ret_str,config_api_num,func_name) ,
    args = ExtractArgumentsList(func)
    arg_ind = 0
    for a in args:
        print "%s" % a ,
        if arg_ind == len(args)-1:
            break
        arg_ind+=1
        print "," ,
    print ");"
    print "}\n"
    